package lmh.example.exam2_9;


import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLSurfaceView;
import android.opengl.GLUtils;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

public class MyRenderer implements GLSurfaceView.Renderer
{
    float[] triangleData = new float[] {
            -1f, 1f , 0.0f , // 左上顶点
            1f, 1f , 0.0f , // 右上顶点
            -1f, -1f , 0.0f  // 左下顶点
    };
    float[] VERTEX = {   // in counterclockwise order:
            0f, 0f, 0f,// bottom left
            1f, 0f, 0f,  // top right
            0f, 1f, 0f, // top left
    };
    int texture;
    FloatBuffer cubeTexturesBuffer;
    FloatBuffer triangleDataBuffer;
    private Context context;
    public MyRenderer(Context main)
    {
        this.context=main;
        // 将顶点位置数据数组转换成FloatBuffer
        triangleDataBuffer = floatBufferUtil(triangleData);
        cubeTexturesBuffer= floatBufferUtil(VERTEX);
    }
    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config)
    {
        // 关闭抗抖动
        gl.glDisable(GL10.GL_DITHER);
        // 设置系统对透视进行修正
        gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT
                , GL10.GL_FASTEST);
        gl.glClearColor(0, 0, 0, 0);
        // 设置阴影平滑模式
        gl.glShadeModel(GL10.GL_SMOOTH);
        // 启用深度测试
        gl.glEnable(GL10.GL_DEPTH_TEST);
        // 启用2D纹理贴图
        gl.glEnable(GL10.GL_TEXTURE_2D);
        // 设置深度测试的类型
        gl.glDepthFunc(GL10.GL_LEQUAL);
        loadTexture(gl);
    }
    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height)
    {
        // 设置3D视窗的大小及位置
        gl.glViewport(0, 0, width, height);
        // 将当前矩阵模式设为投影矩阵
        gl.glMatrixMode(GL10.GL_PROJECTION);
        // 初始化单位矩阵
        gl.glLoadIdentity();
        // 计算透视视窗的宽度、高度比
        float ratio = (float) width / height;
        // 调用此方法设置透视视窗的空间大小
        gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10);
    }
    // 绘制图形的方法
    @Override
    public void onDrawFrame(GL10 gl)
    {
        // 清除屏幕缓存和深度缓存
        gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
        // 启用顶点坐标数据
        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
        // 启用贴图坐标数组数据
        gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);   // ①
        // 设置当前矩阵模式为模型视图。
        gl.glMatrixMode(GL10.GL_MODELVIEW);
        gl.glLoadIdentity();
        gl.glTranslatef(-0.0f, 0.0f, -2.0f);  // ①
        // 设置顶点的位置数据
        gl.glVertexPointer(3, GL10.GL_FLOAT, 0, triangleDataBuffer);
        // 设置贴图的坐标数据
        gl.glTexCoordPointer(3, GL10.GL_FLOAT, 0, cubeTexturesBuffer);  // ②
        // 执行纹理贴图
        gl.glBindTexture(GL10.GL_TEXTURE_2D, texture);  // ③
        // 根据顶点数据绘制平面图形
        gl.glDrawArrays(GL10.GL_TRIANGLES, 0, 3);
        // 绘制结束
        gl.glFinish();
        // 禁用顶点、纹理坐标数组
        gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
        gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);

    }
    private void loadTexture(GL10 gl)
    {
        Bitmap bitmap = null;
        try
        {
            // 加载位图
            bitmap = BitmapFactory.decodeResource(context.getResources(),
                    R.drawable.bg);
            int[] textures = new int[1];
            // 指定生成N个纹理（第一个参数指定生成一个纹理）
            // textures数组将负责存储所有纹理的代号
            gl.glGenTextures(1, textures, 0);
            // 获取textures纹理数组中的第一个纹理
            texture = textures[0];
            // 通知OpenGL将texture纹理绑定到GL10.GL_TEXTURE_2D目标中
            gl.glBindTexture(GL10.GL_TEXTURE_2D, texture);
            // 设置纹理被缩小（距离视点很远时被缩小）时的滤波方式
            gl.glTexParameterf(GL10.GL_TEXTURE_2D,
                    GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
            // 设置纹理被放大（距离视点很近时被方法）时的滤波方式
            gl.glTexParameterf(GL10.GL_TEXTURE_2D,
                    GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
            // 设置在横向、纵向上都是平铺纹理
            gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S,
                    GL10.GL_REPEAT);
            gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T,
                    GL10.GL_REPEAT);
            // 加载位图生成纹理
            GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);
        }
        finally
        {
            // 生成纹理之后，回收位图
            if (bitmap != null)
                bitmap.recycle();
        }
    }
    // 定义一个工具方法，将float[]数组转换为OpenGL ES所需的FloatBuffer
    private FloatBuffer floatBufferUtil(float[] arr)
    {
        FloatBuffer mBuffer;
        // 初始化ByteBuffer，长度为arr数组的长度*4，因为一个float占4字节
        ByteBuffer qbb = ByteBuffer.allocateDirect(arr.length * 4);
        // 数组排列用nativeOrder
        qbb.order(ByteOrder.nativeOrder());
        mBuffer = qbb.asFloatBuffer();
        mBuffer.put(arr);
        mBuffer.position(0);
        return mBuffer;
    }
}